package cn.huiyunche.driver.service.impl;

import cn.huiyunche.base.service.interfaces.DVehicleClassifyService;
import cn.huiyunche.base.service.mappers.DVehiclePreKilometerFeeEffectiveMapper;
import cn.huiyunche.base.service.mappers.ext.DVehiclePreKilometerFeeEffectiveExtMapper;
import cn.huiyunche.base.service.model.DRouteVehiclePriceEffective;
import cn.huiyunche.base.service.model.DVehicleClassify;
import cn.huiyunche.base.service.model.DVehiclePreKilometerFeeEffective;
import cn.huiyunche.base.service.model.DVehiclePreKilometerFeeEffectiveExample;
import cn.huiyunche.base.service.vo.DRouteVehiclePriceEffectiveVo;
import cn.huiyunche.base.service.vo.DVehiclePreKilometerFeeEffectiveVo;
import cn.huiyunche.base.service.vo.PageVo;
import cn.huiyunche.driver.service.DRouteVehiclePriceEffectiveService;
import cn.huiyunche.driver.service.DVehiclePreKilometerFeeEffectiveService;
import cn.huiyunche.driver.service.query.DRouteVehiclePriceEffectiveQueryConditions;
import cn.huiyunche.driver.service.query.DVehiclePreKilometerFeeEffectiveQueryConditions;
import cn.huiyunche.tools.basic.exceptions.BusinessException;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * @FileName: cn.huiyunche.driver.service.impl
 * @Description: Description
 * @author: Aaron
 * @date: 2017/2/26 下午9:45
 */
@Service
public class DVehiclePreKilometerFeeEffectiveServiceImpl implements DVehiclePreKilometerFeeEffectiveService {

    private static final Logger LOGGER = LoggerFactory.getLogger(DVehiclePreKilometerFeeEffectiveServiceImpl.class);

    @Autowired
    private DVehiclePreKilometerFeeEffectiveMapper dVehiclePreKilometerFeeEffectiveMapper;

    @Autowired
    private DVehicleClassifyService dVehicleClassifyService;

    @Autowired
    private DVehiclePreKilometerFeeEffectiveExtMapper dVehiclePreKilometerFeeEffectiveExtMapper;

    @Autowired
    private DRouteVehiclePriceEffectiveService dRouteVehiclePriceEffectiveService;

    @Override
    public Integer add(DVehiclePreKilometerFeeEffective dVehiclePreKilometerFeeEffective) {
        LOGGER.info("DVehiclePreKilometerFeeEffectiveServiceImpl.add params : {}", dVehiclePreKilometerFeeEffective);

        if (null == dVehiclePreKilometerFeeEffective) {
            LOGGER.error("DVehiclePreKilometerFeeEffectiveServiceImpl.add param dVehiclePreKilometerFeeEffective must not be null");
            throw new IllegalArgumentException("车型每公里油费变动信息不能为空");
        }

        /**
         * 新增时只允许有一个未激活的车型每公里油费变动
         */
        List<DVehiclePreKilometerFeeEffective> feeEffectives = this.selectNotEffective(dVehiclePreKilometerFeeEffective.getVehicleTypeId());
        if (CollectionUtils.isNotEmpty(feeEffectives)) {
            LOGGER.error("DVehiclePreKilometerFeeEffectiveServiceImpl.add error feeEffectives is not empty ");
            throw new BusinessException("已经存在未激活的车型每公里油费生效信息！");
        }

        /**
         * 新增后设置前一个的失效时间为新增记录的生效时间
         */
        DVehiclePreKilometerFeeEffective feeEffective = this.selectPreviousActive(dVehiclePreKilometerFeeEffective.getVehicleTypeId(), null);
        if (null != feeEffective) {
            feeEffective.setInvalidDate(dVehiclePreKilometerFeeEffective.getEffectiveDate());
            this.update(feeEffective);
        }

        dVehiclePreKilometerFeeEffectiveMapper.insertSelective(dVehiclePreKilometerFeeEffective);

        return dVehiclePreKilometerFeeEffective.getId();
    }

    @Override
    public void automaticGeneration(Integer fuelTypeId, Integer fuelPriceEffectiveId, BigDecimal marketPrice, Date effectiveDate) {
        LOGGER.info("DVehiclePreKilometerFeeEffectiveServiceImpl.add params : {}, {}, {}, {}", fuelTypeId, fuelPriceEffectiveId, marketPrice, effectiveDate);

        if (null == fuelTypeId) {
            LOGGER.error("DVehiclePreKilometerFeeEffectiveServiceImpl.add param fuelTypeId must not be null");
            throw new IllegalArgumentException("费用类型主键不能为空");
        }
        if (null == fuelPriceEffectiveId) {
            LOGGER.error("DVehiclePreKilometerFeeEffectiveServiceImpl.add param fuelPriceEffectiveId must not be null");
            throw new IllegalArgumentException("燃油费用变动主键不能为空");
        }
        if (null == marketPrice) {
            LOGGER.error("DVehiclePreKilometerFeeEffectiveServiceImpl.add param marketPrice must not be null");
            throw new IllegalArgumentException("市场价不能为空");
        }
        if (null == effectiveDate) {
            LOGGER.info("DVehiclePreKilometerFeeEffectiveServiceImpl.add param effectiveDate must not be null");
            throw new IllegalArgumentException("生效时间不能为空");
        }

        //查询燃油类型的所有车型
        List<DVehicleClassify> list = new ArrayList<>();
        try {
            list = dVehicleClassifyService.selectByFuelTypeId(fuelTypeId);
        } catch (Exception e1) {
            LOGGER.error("DVehiclePreKilometerFeeEffectiveServiceImpl.add error: {}", e1);
            throw new IllegalArgumentException("查询车型异常");
        }
        if (CollectionUtils.isNotEmpty(list)) {
            list.stream().forEach(e -> {

                DVehiclePreKilometerFeeEffective vehiclePreKilometerFee = new DVehiclePreKilometerFeeEffective();
                vehiclePreKilometerFee.setVehicleTypeId(Integer.parseInt(e.getId().toString()));
                vehiclePreKilometerFee.setFuelPriceId(fuelPriceEffectiveId);
                vehiclePreKilometerFee.setPerKmOilFee(calcVehiclePreKilometerFee(marketPrice, e.getFuelConsumption()).setScale(2, RoundingMode.HALF_UP));
                vehiclePreKilometerFee.setEffectiveDate(effectiveDate);
                // 通过车型查询所有线路
                DRouteVehiclePriceEffectiveQueryConditions conditions = new DRouteVehiclePriceEffectiveQueryConditions();
                conditions.setVehicleTypeId(e.getId());
                this.add(vehiclePreKilometerFee);
                // 重新计算车型线路
                resetRouteVehiclePriceEffective(dRouteVehiclePriceEffectiveService.selectListByConditions(null, conditions), vehiclePreKilometerFee);
            });
        }
    }

    private void resetRouteVehiclePriceEffective(Map<String, Object> map, DVehiclePreKilometerFeeEffective vehiclePreKilometerFee) {
        LOGGER.info("DVehiclePreKilometerFeeEffectiveServiceImpl.resetRouteVehiclePriceEffective params: {}", map);
        if (null == map) {
            return;
        }
        List<DRouteVehiclePriceEffectiveVo> list = (List<DRouteVehiclePriceEffectiveVo>) map.get("list");
        if (CollectionUtils.isNotEmpty(list)) {
            list.stream().forEach(e -> {
                DRouteVehiclePriceEffective drvpe = new DRouteVehiclePriceEffective();
                drvpe.setId(e.getId());
                drvpe.setTotalPrice(e.getLabourServicesPrice().add(vehiclePreKilometerFee.getPerKmOilFee()));
                dRouteVehiclePriceEffectiveService.update(drvpe);
            });
        }
    }

    private BigDecimal calcVehiclePreKilometerFee(BigDecimal marketPrice, BigDecimal fuelConsumption) {
        LOGGER.info("DVehiclePreKilometerFeeEffectiveServiceImpl.calcVehiclePreKilometerFee params : {}, {}", marketPrice, fuelConsumption);

        //每公里油价
        BigDecimal preKilometerFee;

        if (null == marketPrice) {
            LOGGER.error("DVehiclePreKilometerFeeEffectiveServiceImpl.calcVehiclePreKilometerFee param marketPrice must not be null");
            throw new IllegalArgumentException("市场价不能为空");
        }
        if (null == fuelConsumption) {
            LOGGER.error("DVehiclePreKilometerFeeEffectiveServiceImpl.calcVehiclePreKilometerFee param fuelConsumption must not be null");
            throw new IllegalArgumentException("车型百公里油耗不能为空");
        }

        preKilometerFee = fuelConsumption.divide(BigDecimal.valueOf(100)).multiply(marketPrice);

        return preKilometerFee;
    }

    @Override
    public Map<String, Object> selectListByConditions(PageVo pageVo, DVehiclePreKilometerFeeEffectiveQueryConditions conditions) {
        LOGGER.info("DVehiclePreKilometerFeeEffectiveServiceImpl.selectListByConditions params  : {}, {}", pageVo, conditions);

//        if( null == pageVo ){
//            LOGGER.error("DVehiclePreKilometerFeeEffectiveServiceImpl.selectListByConditions param pageVo must not be null");
//            throw new IllegalArgumentException("分页信息不能为空");
//        }
        if (null == conditions) {
            LOGGER.error("DVehiclePreKilometerFeeEffectiveServiceImpl.selectListByConditions param conditions must not be null");
            throw new IllegalArgumentException("查询条件信息不能为空");
        }

        Map<String, Object> map = new HashMap<>();

        String orderByClause = null;
        if (null != pageVo) {
            orderByClause = StringUtils.isNotBlank(pageVo.getOrder()) == true ? pageVo.getOrder() : " vpkf.create_time DESC";
        }

        DVehiclePreKilometerFeeEffectiveExample example = new DVehiclePreKilometerFeeEffectiveExample();
        DVehiclePreKilometerFeeEffectiveExample.Criteria criteria = example.createCriteria();

        if (null != conditions.getFuelPriceId()) {
            criteria.andFuelPriceIdEqualTo(conditions.getFuelPriceId());
        }
        if (null != conditions.getVehicleTypeId()) {
            criteria.andVehicleTypeIdEqualTo(conditions.getVehicleTypeId());
        }
        if (null != conditions.getEffectiveDate()) {
            criteria.andEffectiveDateGreaterThanOrEqualTo(conditions.getEffectiveDate());
        }
        if (null != conditions.getInvalidDate()) {
            criteria.andInvalidDateLessThanOrEqualTo(conditions.getInvalidDate());
        }

        if (null != pageVo) {
            pageVo.setTotalRecord(dVehiclePreKilometerFeeEffectiveExtMapper.countByExample(example));
            example.setLimitStart(pageVo.getStartIndex());
            example.setLimitEnd(pageVo.getPageSize());
            example.setOrderByClause(orderByClause);
        }

        List<DVehiclePreKilometerFeeEffectiveVo> list = dVehiclePreKilometerFeeEffectiveExtMapper.selectByExample(example);
        map.put("list", list);

        if (null != pageVo) {

            map.put("page", pageVo);
        }

        return map;
    }

    @Override
    public List<DVehiclePreKilometerFeeEffective> selectNotEffective(Integer vehicleTypeId) {
        LOGGER.info("DVehiclePreKilometerFeeEffectiveServiceImpl.selectNotEffective param : {}", vehicleTypeId);

        if (null == vehicleTypeId) {
            LOGGER.error("DVehiclePreKilometerFeeEffectiveServiceImpl.selectNotEffective param vehicleTypeId must not be null");
            throw new IllegalArgumentException("车型主键不能为空");
        }

        DVehiclePreKilometerFeeEffectiveExample example = new DVehiclePreKilometerFeeEffectiveExample();
        example.createCriteria().andVehicleTypeIdEqualTo(vehicleTypeId).andInvalidDateIsNull();
        List<DVehiclePreKilometerFeeEffective> list = dVehiclePreKilometerFeeEffectiveMapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(list)) {
            DVehiclePreKilometerFeeEffective effective = list.get(0);
            Date currentDate = new Date();
            if (null == effective.getInvalidDate() && currentDate.before(effective.getEffectiveDate())) {
                return list;
            }
        }
        return null;
    }

    @Override
    public DVehiclePreKilometerFeeEffective selectPreviousActive(Integer vehicleTypeId, Date invalidDate) {
        LOGGER.info("DVehiclePreKilometerFeeEffectiveServiceImpl.selectCurrentlyActive param : {}", vehicleTypeId);

        if (null == vehicleTypeId) {
            LOGGER.error("DVehiclePreKilometerFeeEffectiveServiceImpl.selectCurrentlyActive param vehicleTypeId must not be null");
            throw new IllegalArgumentException("车型类型主键不能为空");
        }

        DVehiclePreKilometerFeeEffectiveExample example = new DVehiclePreKilometerFeeEffectiveExample();
        DVehiclePreKilometerFeeEffectiveExample.Criteria criteria = example.createCriteria()
                .andVehicleTypeIdEqualTo(vehicleTypeId)
                .andEffectiveDateLessThanOrEqualTo(new Date());
        if (null != invalidDate) {
            criteria.andInvalidDateLessThanOrEqualTo(invalidDate);
        } else {
            criteria.andInvalidDateIsNull();
        }

        List<DVehiclePreKilometerFeeEffective> feeEffectives = dVehiclePreKilometerFeeEffectiveMapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(feeEffectives)) {
            return feeEffectives.get(0);
        }

        return null;
    }

    @Override
    public void update(DVehiclePreKilometerFeeEffective feeEffective) {
        LOGGER.info("DVehiclePreKilometerFeeEffectiveServiceImpl.update param : {}", feeEffective);

        if (null == feeEffective) {
            LOGGER.error("DVehiclePreKilometerFeeEffectiveServiceImpl.update param feeEffective must not be null");
            throw new IllegalArgumentException("车型每公里油费变动信息不能为空");
        }

        dVehiclePreKilometerFeeEffectiveMapper.updateByPrimaryKeySelective(feeEffective);
    }

    @Override
    public List<DVehiclePreKilometerFeeEffective> selectListByConditions(DVehiclePreKilometerFeeEffectiveQueryConditions conditions) {
        LOGGER.info("DVehiclePreKilometerFeeEffectiveServiceImpl.selectListByConditions param : {}", conditions);

//        if( null == conditions ){
//            LOGGER.error("DVehiclePreKilometerFeeEffectiveServiceImpl.selectListByConditions param conditions must not be null");
//            throw new IllegalArgumentException("查询条件不能为空");
//        }

        DVehiclePreKilometerFeeEffectiveExample example = new DVehiclePreKilometerFeeEffectiveExample();
        DVehiclePreKilometerFeeEffectiveExample.Criteria criteria = example.createCriteria();

        if (null != conditions) {
            if (null != conditions.getFuelPriceId()) {
                criteria.andFuelPriceIdEqualTo(conditions.getFuelPriceId());
            }
            if (null != conditions.getVehicleTypeId()) {
                criteria.andVehicleTypeIdEqualTo(conditions.getVehicleTypeId());
            }
            if (null != conditions.getEffectiveDate()) {
                criteria.andEffectiveDateGreaterThanOrEqualTo(conditions.getEffectiveDate());
            }
            if (null != conditions.getInvalidDate()) {
                criteria.andInvalidDateLessThanOrEqualTo(conditions.getInvalidDate());
            }
        }

        return dVehiclePreKilometerFeeEffectiveMapper.selectByExample(example);
    }

    @Override
    public void updateByDFuelPriceEffective(Integer fuelPriceEffectiveId, BigDecimal marketPrice, Date effectiveDate) {
        LOGGER.info("DVehiclePreKilometerFeeEffectiveServiceImpl.updateByDFuelPriceEffective params : {}, {}, {}", fuelPriceEffectiveId, marketPrice, effectiveDate);

        if (null == fuelPriceEffectiveId) {
            LOGGER.error("DVehiclePreKilometerFeeEffectiveServiceImpl.add param fuelPriceEffectiveId must not be null");
            throw new IllegalArgumentException("燃油费用变动主键不能为空");
        }
        if (null == marketPrice) {
            LOGGER.error("DVehiclePreKilometerFeeEffectiveServiceImpl.add param marketPrice must not be null");
            throw new IllegalArgumentException("市场价不能为空");
        }
        if (null == effectiveDate) {
            LOGGER.info("DVehiclePreKilometerFeeEffectiveServiceImpl.add param effectiveDate must not be null");
            throw new IllegalArgumentException("生效时间不能为空");
        }

        /**
         * 根据燃油价格变动记录主键查询车型每公里油费变动
         */
        DVehiclePreKilometerFeeEffectiveQueryConditions conditions = new DVehiclePreKilometerFeeEffectiveQueryConditions();
        conditions.setFuelPriceId(fuelPriceEffectiveId);
        List<DVehiclePreKilometerFeeEffective> list = this.selectListByConditions(conditions);
        if (CollectionUtils.isNotEmpty(list)) {
            list.stream().forEach(e -> {

                /**
                 * 更新上一个激活的记录的失效时间
                 */
                DVehiclePreKilometerFeeEffective vehiclePreKilometerFeeEffective = this.selectPreviousActive(e.getVehicleTypeId(), e.getEffectiveDate());
                if (null != vehiclePreKilometerFeeEffective) {
                    vehiclePreKilometerFeeEffective.setInvalidDate(effectiveDate);
                    this.update(e);
                }

                //查询车型油耗
                DVehicleClassify bVehicleType = new DVehicleClassify();
                try {
                    bVehicleType = dVehicleClassifyService.selectByPrimaryId(e.getVehicleTypeId());
                } catch (Exception e1) {
                    LOGGER.error("DVehiclePreKilometerFeeEffectiveServiceImpl.add error: {}", e);
                    throw new IllegalArgumentException("查询车型油耗异常");
                }

                e.setPerKmOilFee(calcVehiclePreKilometerFee(marketPrice, bVehicleType.getFuelConsumption()).setScale(2, RoundingMode.HALF_UP));
                e.setEffectiveDate(effectiveDate);
                this.update(e);
            });
        }

    }

    @Override
    public DVehiclePreKilometerFeeEffective selectActivedByEffectiveDate(Integer vehicleTypeId, Date effectiveDate) {
        LOGGER.info("DVehiclePreKilometerFeeEffectiveServiceImpl.selectActivedByEffectiveDate params : {}, {}", vehicleTypeId, effectiveDate);

        if (null == vehicleTypeId || 0 == vehicleTypeId.intValue()) {
            LOGGER.error("DVehiclePreKilometerFeeEffectiveServiceImpl.selectActivedByEffectiveDate param vehicleTypeId must not be null");
            throw new IllegalArgumentException("车型分类主键不能为空");
        }

        if (null == effectiveDate) {
            LOGGER.error("DVehiclePreKilometerFeeEffectiveServiceImpl.selectActivedByEffectiveDate param effectiveDate must not be null");
            throw new IllegalArgumentException("激活时间不能为空");
        }

        List<DVehiclePreKilometerFeeEffective> list;

        DVehiclePreKilometerFeeEffectiveExample example = new DVehiclePreKilometerFeeEffectiveExample();
        example.createCriteria().andVehicleTypeIdEqualTo(vehicleTypeId)
                .andEffectiveDateLessThanOrEqualTo(effectiveDate)
                .andInvalidDateIsNull();

        list = dVehiclePreKilometerFeeEffectiveMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(list)) {
            DVehiclePreKilometerFeeEffectiveExample example1 = new DVehiclePreKilometerFeeEffectiveExample();
            example1.createCriteria().andVehicleTypeIdEqualTo(vehicleTypeId)
                    .andEffectiveDateLessThanOrEqualTo(effectiveDate)
                    .andInvalidDateGreaterThan(new Date());

            list = dVehiclePreKilometerFeeEffectiveMapper.selectByExample(example1);
        }

        if (CollectionUtils.isNotEmpty(list)) {
            return list.get(0);
        }

        return null;
    }
}
